package com.example.demo.controller

import com.example.demo.dao.*
import com.example.demo.dao.Tables.tBeds
import com.example.demo.dao.Tables.tCareLabels
import com.example.demo.dao.Tables.tDepts
import com.example.demo.dao.Tables.tDevices
import com.example.demo.dao.Tables.tDistricts
import com.example.demo.dao.Tables.tDoctorOrders
import com.example.demo.dao.Tables.tDoctors
import com.example.demo.dao.Tables.tFees
import com.example.demo.dao.Tables.tHospitals
import com.example.demo.dao.Tables.tNurses
import com.example.demo.dao.Tables.tPatientCareLabelRefs
import com.example.demo.dao.Tables.tPatients
import com.example.demo.dao.Tables.tPressures
import com.example.demo.dao.Tables.tRooms
import com.example.demo.dao.Tables.tTemperatures
import com.example.demo.dbmodels.TDept
import com.example.demo.service.BedService
import com.example.demo.service.impl.BoardServiceImpl
import com.example.demo.utils.GmrDatabase
import com.example.demo.utils.LogUtils
import com.example.demo.utils.WebDatabase
import com.example.demo.vo.*
import com.example.demo.vo.board.NurseLevelVo
import me.liuwj.ktorm.dsl.*
import me.liuwj.ktorm.dsl.update
import me.liuwj.ktorm.entity.*
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.logging.Logger


@Service
class BedServiceImpl(
        @Autowired
        private val webDatabase: WebDatabase,
        @Autowired
        private val gmrDatabase: GmrDatabase
) : BedService {


    private val logger = LoggerFactory.getLogger(BedServiceImpl::class.java)

    //    xh08    1402
    override fun getBedCardInfo(deptCode: String, bedCode: String): BedInfoVo? {
        val bedInfoVo = BedInfoVo()
        var patientVo: PatientVo? = null
        var doctorVo: DoctorVo? = null
        var nurseVo: NurseVo? = null
        var nurseLevelVo: NurseLevelVo? = null
        val patientCareLabelRefVoList = mutableListOf<PatientCareLabelRefVo>()
        var patientCareLabelRefVo: PatientCareLabelRefVo? = null
        gmrDatabase.getDataBase().from(TPatientDao)
                .leftJoin(TDoctorDao, on = TPatientDao.doctor_code eq TDoctorDao.code)
                .leftJoin(TNurseDao, on = TPatientDao.nurse_code eq TNurseDao.code)
                .leftJoin(TPatientCareLabelRefDao, on = TPatientDao.cure_no eq TPatientCareLabelRefDao.patient_id)
                .leftJoin(TNurseLevelDao, on = TPatientDao.nurse_level_code eq TNurseLevelDao.level_code)
                .select()
                .where { (TPatientDao.dept_code eq deptCode) and (TPatientDao.bed_code eq bedCode) }
                .forEach {
                    patientVo = PatientVo().getVo(it)
                    doctorVo = DoctorVo().getDoctorVo(it)
                    nurseVo = NurseVo().getDoctorVo(it)
                    nurseLevelVo = NurseLevelVo().getVoQuery(it)
                    patientCareLabelRefVo = PatientCareLabelRefVo().getVo(it)
                    patientCareLabelRefVo?.let {
                        patientCareLabelRefVoList.add(it)
                    }
                }

        bedInfoVo.patientVo = patientVo
        bedInfoVo.doctorVo = doctorVo
        bedInfoVo.nurseVo = nurseVo
        bedInfoVo.nurseLevel = nurseLevelVo
        bedInfoVo.patientCareLabelRefVo = patientCareLabelRefVoList
        val careLabelVoList = mutableListOf<CareLabelVo>()
        bedInfoVo.patientCareLabelRefVo?.forEach { patientCareLabelRefVo ->
            gmrDatabase.getDataBase().tCareLabels.find {
                it.label_code eq patientCareLabelRefVo.care_label_id.toString()
            }?.let {
                val careLabelVo = CareLabelVo().getCareLabelVo(it)
                careLabelVo?.let {
                    careLabelVoList.add(it)
                }
            }
        }
        bedInfoVo.bedSideCareLabelVo = careLabelVoList
        return bedInfoVo

    }

    override fun getDeptList(): List<DeptVo>? {
        gmrDatabase.getDataBase().tDepts.toList().let {
            DeptVo().getListVo(it).let {
                return it
            }
        }
    }

    override fun getBindToBed(
            deptCode: String?,
            deptName: String?,
            bedCode: String?,
            bedName: String?,
            deviceNo: String?,
            deviceMac: String?,
            deviceIp: String?,
            appVersion: String?,
            deviceType: String?
    ): Int? {
        deviceNo?.let {
            webDatabase.getDataBase().tDevices.filter {
                it.device_no eq deviceNo
            }.firstOrNull()?.let {
                webDatabase.getDataBase().update(TDeviceDao) {
                    set(it.dept_code, deptCode)
                    set(it.app_version, appVersion)
                    set(it.device_ip, deviceIp)
                    set(it.device_mac, deviceMac)
                    set(it.device_type, deviceType?.toInt())
                    set(it.device_no, deviceNo)
                    set(it.register_bed, bedName)
                    where {
                        it.device_no eq deviceNo
                    }
                }.let {
                    return it
                }
            } ?: let {
                webDatabase.getDataBase().insertAndGenerateKey(TDeviceDao) {
                    set(it.dept_code, deptCode)
                    set(it.app_version, appVersion)
                    set(it.device_ip, deviceIp)
                    set(it.device_mac, deviceMac)
                    set(it.device_type, deviceType?.toInt())
                    set(it.device_no, deviceNo)
                    set(it.register_bed, bedName)
                }.let {
                    return it.toString().toInt()
                }
            }
        }
        return null
    }

    override fun getBedList(deptCode: String): List<BedVo>? {
        gmrDatabase.getDataBase().tBeds.filter {
            it.dept_code eq deptCode
        }.toList().let {
            return BedVo().getListVo(it)
        }
    }

    override fun editBedList(deptCode: String) {
//        gmrDatabase.getDataBase().update(TBedDao) {
//            set(it.bed_code, deptCode)
//            where {
//                it.dept_code eq "790"
//            }
//        }
        gmrDatabase.getDataBase().tBeds.filter {
            it.dept_code eq "1402"
        }.toList().forEachIndexed { index, tBed ->
             var bedname =""
           var i= index + 1
            if(i<10){
                bedname= "xh0${i}"
                LogUtils.e(bedname)
            }else{
                bedname= "xh${i}"
                LogUtils.e(bedname)
            }
            val bed = BedVo().getVo(tBed)


        gmrDatabase.getDataBase().update(TBedDao) {
            set(it.bed_name, bedname)
            where {
                it.id eq bed.id!!
            }
        }


        }
    }

    override fun getDeptDiviceNo(deptCode: String): DeptDeviceNoVO? {
        webDatabase.getDataBase().tDevices.filter {
            it.device_type eq 2
        }.filter {
            it.dept_code eq deptCode
        }.firstOrNull()?.let {
            val deptDeviceNoVO = DeptDeviceNoVO()
            deptDeviceNoVO.deviceNo = DeviceVo().getVo(it).device_no
            return deptDeviceNoVO
        } ?: return null
    }

    override fun addTermometerValue(
            patientId: Int?,
            patientName: String?,
            deptId: Int?,
            deptName: String?,
            bedId: Int?,
            bedName: String?,
            date: String?,
            temperature: String?
    ): Int? {
        webDatabase.getDataBase().insertAndGenerateKey(TTemperatureDao) {
            set(it.patient_id, patientId)
            set(it.patient_name, patientName)
            set(it.dept_id, deptId)
            set(it.dept_name, deptName)
            set(it.bed_id, bedId)
            set(it.bed_name, bedName)
            set(it.date, date)
            set(it.temperature, temperature)
        }.let {
            return it.toString().toInt()
        }
    }


    //    override fun addPressureValue(
//        patientId: Int?,
//        patientName: String?,
//        deptId: Int?,
//        deptName: String?,
//        bedId: Int?,
//        bedName: String?,
//        date: String?,
//        highPress: String?,
//        lowPress: String?,
//        heartRate: String?
//    ): Int? {
//        webDatabase.getDataBase().insertAndGenerateKey(TPressureDao) {
//            set(it.patientId, patientId)
//            set(it.patientName, patientName)
//            set(it.deptId, deptId)
//            set(it.deptName, deptName)
//            set(it.bedId, bedId)
//            set(it.bedName, bedName)
//            set(it.date, date)
//            set(it.highPress, highPress)
//            set(it.lowPress, lowPress)
//            set(it.heartRate, heartRate)
//        }.let {
//            return it.toString().toInt()
//        }
//    }
//
    override fun getPressureValue(patientId: Int): PressureVo? {
        webDatabase.getDataBase().tPressures.find {
            it.id eq patientId
        }?.let {
            return PressureVo().getVo(it)
        }
        return null
    }

    override fun getPressureValueList(patientId: Int): List<PressureVo>? {
        webDatabase.getDataBase().tPressures.filter {
            it.id eq patientId
        }.toList().let {
            return PressureVo().getVoList(it)
        }
    }

    //    override fun getPressureValueList(deptId: Int?, patientId: Int?, patientName: String?): List<PressureVo>? {
//        webDatabase.getDataBase()
//            .from(TPressureDao)
//            .select()
//            .whereWithConditions {
//                deptId?.let { deptId ->
//                    it += TPressureDao.deptId eq deptId
//                }
//                patientId?.let { patientId ->
//                    it += TPressureDao.patientId eq patientId
//                }
//                patientName?.let { patientName ->
//                    it += TPressureDao.patientName eq patientName
//                }
//            }.let { query ->
//                val pressureVoList = mutableListOf<PressureVo>()
//                query.forEach {
//                    pressureVoList.add(PressureVo().getVo(it))
//                }
//                return pressureVoList
//            }
//    }
//
//    override fun getBoardMessage(deptId: Int?, messageType: String?, start: Int, end: Int): List<BoardMessageVo>? {
//        webDatabase.getDataBase()
//            .from(TBoardMessageDao)
//            .select()
//            .whereWithConditions {
//                deptId?.let { deptId ->
//                    it += TBoardMessageDao.deptId eq deptId
//                }
//                messageType?.let { messageType ->
//                    it += TBoardMessageDao.messageType eq messageType
//                }
//            }
//            .limit(start, end)
//            .orderBy(TBoardMessageDao.id.desc())
//            .let {
//                val boardMessageVoList = mutableListOf<BoardMessageVo>()
//                it.forEach {
//                    boardMessageVoList.add(BoardMessageVo().getVo(it))
//                }
//                return boardMessageVoList
//            }
//    }
//
    override fun getFeeList(patientId: String): List<FeeVo> {
        gmrDatabase.getDataBase().tFees.filter {
            it.patient_code eq patientId
        }.toList().let {
            return FeeVo().getListVo(it)
        }
    }


    override fun getListHospital(): List<HospitalVo>? {
        gmrDatabase.getDataBase().tHospitals.toList()?.let {
            return HospitalVo().getHospitalListVo(it)
        } ?: return null
    }

    override fun getDistrict(): List<DistrictVo>? {
        gmrDatabase.getDataBase().tDistricts.toList().let {
            return DistrictVo().getDistrict(it)
        }
    }

    override fun getListRoom(deptCode: String, districtCode: String): List<RoomVo>? {
        gmrDatabase.getDataBase().tRooms.filter {
            it.dept_code eq deptCode
        }.filter {
            it.district_code eq districtCode
        }.toList()?.let {
            return RoomVo().getListRoomVo(it)
        }
    }

    override fun getDeptInfo(deptCode: String): DeptVo? {
        gmrDatabase.getDataBase().tDepts.find {
            it.code eq deptCode
        }?.let {
            return DeptVo().getVo(it)
        }
        return null
    }

    override fun getTermometerValue(patientId: Int): TemperatureVo? {
        gmrDatabase.getDataBase().tTemperatures.find {
            it.patient_id eq patientId
        }?.let {
            return TemperatureVo().getVo(it)
        }
        return null
    }

    override fun getTermometerValueList(patientId: Int): List<TemperatureVo>? {
        gmrDatabase.getDataBase().tTemperatures.filter {
            it.patient_id eq patientId
        }.toList().let {
            return TemperatureVo().getVoList(it)
        }
    }

    override fun getDoctorList(): List<DoctorVo>? {
        gmrDatabase.getDataBase().tDoctors.toList().let {
            return DoctorVo().getDoctorVoList(it)
        }
    }

    override fun getNurseList(): List<NurseVo>? {
        val query = gmrDatabase.getDataBase().tNurses
        logger.error(query.sql)
        query.toList().let {
            return NurseVo().getNurseVoList(it)
        }
    }

    override fun getDoctorOrderList(patientId: String, page: Int): List<DoctorOrderVo>? {
        val query = gmrDatabase.getDataBase().from(TDoctorOrderDao).select().where { TDoctorOrderDao.patient_cure_no eq patientId }.limit(page, 10)
        logger.error(query.sql)
        val doctorOrderVoList = mutableListOf<DoctorOrderVo>()
        query.forEach {
            DoctorOrderVo().getDoctorOrderVo(it)?.let { it1 -> doctorOrderVoList.add(it1) }
        }
        return doctorOrderVoList
    }

}

